/**
 * create by zhangpu date:2015年3月12日
 */
package com.acooly.module.openapi.client.provider.alipay.marshall;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.MessageFactory;
import com.acooly.module.openapi.client.provider.alipay.AlipayConstants;
import com.acooly.module.openapi.client.provider.alipay.OpenAPIClientAlipayProperties;
import com.acooly.module.openapi.client.provider.alipay.domain.AlipayNotify;
import com.acooly.module.openapi.client.provider.alipay.support.AlipayAlias;
import com.alipay.api.internal.util.AlipaySignature;

import lombok.extern.slf4j.Slf4j;

/**
 * @author zhangpu
 */
@Service
@Slf4j
public class AlipayNotifyUnmarshall
        implements ApiUnmarshal<AlipayNotify, Map<String, String>> {
    private static final Logger logger = LoggerFactory.getLogger(AlipayNotifyUnmarshall.class);

    @Resource(name = "alipayMessageFactory")
    private MessageFactory messageFactory;
    @Autowired
    private OpenAPIClientAlipayProperties openAPIClientAlipayProperties; 
    
    @Override
    public AlipayNotify unmarshal(Map<String, String> notifyMessage, String serviceName) {
        try {
            log.info("异步通知报文{}", notifyMessage);   
            verifySign(notifyMessage);
            return doUnmarshall(notifyMessage, serviceName);
        } catch (Exception e) {
            throw new ApiClientException("异步通知 解析失败:" + e.getMessage());
        }
    }

    protected AlipayNotify doUnmarshall(Map<String, String> message, String serviceName) {
    	AlipayNotify notify =
                (AlipayNotify) messageFactory.getNotify(serviceName);
        Set<Field> fields = Reflections.getFields(notify.getClass());
        String key = null;
        for (Field field : fields) {
            AlipayAlias alias = field.getAnnotation(AlipayAlias.class);
            if (alias != null && Strings.isNotBlank(alias.value())) {
                key = alias.value();
            } else {
                key = field.getName();
            }
            Reflections.invokeSetter(notify, field.getName(), message.get(key));
        }
        return notify;
    }

    public void verifySign(Map<String, String> params) {
        try {
            if (AlipaySignature.rsaCheckV1(params, openAPIClientAlipayProperties.getAppPublicKey(), 
					AlipayConstants.CHARSET,AlipayConstants.SIGN_TYPE)){
				throw new ApiClientException("通知验签失败");
			}
            log.info("验签成功");
        } catch (Exception e) {
            log.info("验签失败，响应报文：{}", params);
            throw new ApiClientException("响应报文验签失败");
        }
    }

    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }
}
